/*-
 * Copyright (c) 2012-2013 Shang-Rong Cai. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $ MTBLAS TEST: tst_lv_a_com.h    Rev. 0.0.18    2013-11-15T14:26+08:00 $
 */

#include <stdlib.h>
#include <time.h>

#include <bscerr.h>

#include <stblas.h>
#include <mtblas.h>

#ifndef TST_LV_A_COM_H
#define TST_LV_A_COM_H

#define TEST_THRZ 4


#define LV1_VECTOR_MIN 100000000
#define LV1_VECTOR_MAX 400000000
#define LV1_VECTOR_RUN 100000000
/*
#define LV1_VECTOR_MIN 10
#define LV1_VECTOR_MAX 40
#define LV1_VECTOR_RUN 10
*/
/*
#define PROPER_VECTOR_MIN  4000
#define PROPER_VECTOR_MAX 16000

#define PROPER_VECTOR_RUN  4000

#define PROPER_MATRIX_MIN  4000
#define PROPER_MATRIX_MAX 16000

#define PROPER_R_SIZE_RUN 3600
#define PROPER_C_SIZE_RUN 2800
#define PROPER_K_SIZE_RUN 4000
*/

#define PROPER_VECTOR_MIN 1000
#define PROPER_VECTOR_MAX 4000

#define PROPER_VECTOR_RUN 1000

#define PROPER_MATRIX_MIN 1000
#define PROPER_MATRIX_MAX 4000

#define PROPER_R_SIZE_RUN  900
#define PROPER_C_SIZE_RUN  700
#define PROPER_K_SIZE_RUN 1000

/*
#define PROPER_VECTOR_MIN 100
#define PROPER_VECTOR_MAX 400

#define PROPER_VECTOR_RUN 100

#define PROPER_MATRIX_MIN 100
#define PROPER_MATRIX_MAX 400

#define PROPER_R_SIZE_RUN  90
#define PROPER_C_SIZE_RUN  70
#define PROPER_K_SIZE_RUN 100
*/
/*
#define PROPER_VECTOR_MIN 10
#define PROPER_VECTOR_MAX 40

#define PROPER_VECTOR_RUN 10

#define PROPER_MATRIX_MIN 10
#define PROPER_MATRIX_MAX 40

#define PROPER_R_SIZE_RUN  9
#define PROPER_C_SIZE_RUN  7
#define PROPER_K_SIZE_RUN 10
*/


inline float random_float()
{
    return (float) random() / (float) random() - (float) random() / (float) random();
}


inline double random_double()
{
    return (double) random() / (double) random() - (double) random() / (double) random();
}


inline long double random_long_double()
{
    return (long double) random() / (long double) random() - (long double) random() / (long double) random();
}


#define ZERO_FREQUENCY 5

extern float rand_coef_ff();

extern double rand_coef_df();

extern long double rand_coef_lf();


extern float complex rand_coef_fc();

extern double complex rand_coef_dc();

extern long double complex rand_coef_lc();


extern void check_value_ff_stdout(char *msg, float val);

extern void check_value_df_stdout(char *msg, double val);

extern void check_value_lf_stdout(char *msg, long double val);


extern void check_value_fc_stdout(char *msg, float complex val);

extern void check_value_dc_stdout(char *msg, double complex val);

extern void check_value_lc_stdout(char *msg, long double complex val);


/* Vector Type */
typedef struct
{
    size_t size;
    step_t step;
    float *data;
} vec_ff_t;

extern int vec_ff_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_ff_t *vx);

extern int vec_ff_delete(vec_ff_t *vx);

extern int vec_ff_twins_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_ff_t *vx, vec_ff_t *vy);

extern int vec_ff_twins_reset(vec_ff_t *vx, vec_ff_t *vy);


typedef struct
{
    size_t size;
    step_t step;
    double *data;
} vec_df_t;

extern int vec_df_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_df_t *vx);

extern int vec_df_delete(vec_df_t *vx);

extern int vec_df_twins_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_df_t *vx, vec_df_t *vy);

extern int vec_df_twins_reset(vec_df_t *vx, vec_df_t *vy);


typedef struct
{
    size_t size;
    step_t step;
    long double *data;
} vec_lf_t;

extern int vec_lf_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_lf_t *vx);

extern int vec_lf_delete(vec_lf_t *vx);

extern int vec_lf_twins_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_lf_t *vx, vec_lf_t *vy);

extern int vec_lf_twins_reset(vec_lf_t *vx, vec_lf_t *vy);


typedef struct
{
    size_t size;
    step_t step;
    float complex *data;
} vec_fc_t;


extern int vec_fc_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_fc_t *vx);

extern int vec_fc_delete(vec_fc_t *vx);

extern int vec_fc_twins_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_fc_t *vx, vec_fc_t *vy);

extern int vec_fc_twins_reset(vec_fc_t *vx, vec_fc_t *vy);


typedef struct
{
    size_t size;
    step_t step;
    double complex *data;
} vec_dc_t;


extern int vec_dc_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_dc_t *vx);

extern int vec_dc_delete(vec_dc_t *vx);

extern int vec_dc_twins_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_dc_t *vx, vec_dc_t *vy);

extern int vec_dc_twins_reset(vec_dc_t *vx, vec_dc_t *vy);


typedef struct
{
    size_t size;
    step_t step;
    long double complex *data;
} vec_lc_t;


extern int vec_lc_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_lc_t *vx);

extern int vec_lc_delete(vec_lc_t *vx);

extern int vec_lc_twins_create(size_t max_sz, size_t min_sz, size_t run_sz, vec_lc_t *vx, vec_lc_t *vy);

extern int vec_lc_twins_reset(vec_lc_t *vx, vec_lc_t *vy);


/* Matrix Type */
typedef struct
{
    size_t row_size;  /* Number of rows */
    size_t col_size;  /* Numbor of columns */
    size_t size;  /* Total size = row_size * col_size */

    float *data;
} mat_ff_t;

extern int mat_ff_create(size_t max_sz, size_t min_sz, mat_ff_t *ma);

extern int mat_ff_delete(mat_ff_t *ma);

extern int mat_ff_twins_create(size_t max_sz, size_t min_sz, mat_ff_t *ma, mat_ff_t *mb);

extern int mat_ff_twins_reset(mat_ff_t *ma, mat_ff_t *mb);

extern void mat_ff_stdout(mat_ff_t *ma);


typedef struct
{
    size_t row_size;  /* Number of rows */
    size_t col_size;  /* Numbor of columns */
    size_t size;  /* Total size = row_size * col_size */

    double *data;
} mat_df_t;

extern int mat_df_create(size_t max_sz, size_t min_sz, mat_df_t *ma);

extern int mat_df_delete(mat_df_t *ma);

extern int mat_df_twins_create(size_t max_sz, size_t min_sz, mat_df_t *ma, mat_df_t *mb);

extern int mat_df_twins_reset(mat_df_t *ma, mat_df_t *mb);

extern void mat_df_stdout(mat_df_t *ma);


typedef struct
{
    size_t row_size;  /* Number of rows */
    size_t col_size;  /* Numbor of columns */
    size_t size;  /* Total size = row_size * col_size */

    long double *data;
} mat_lf_t;

extern int mat_lf_create(size_t max_sz, size_t min_sz, mat_lf_t *ma);

extern int mat_lf_delete(mat_lf_t *ma);

extern int mat_lf_twins_create(size_t max_sz, size_t min_sz, mat_lf_t *ma, mat_lf_t *mb);

extern int mat_lf_twins_reset(mat_lf_t *ma, mat_lf_t *mb);

extern void mat_lf_stdout(mat_lf_t *ma);


typedef struct
{
    size_t row_size;  /* Number of rows */
    size_t col_size;  /* Numbor of columns */
    size_t size;  /* Total size = row_size * col_size */

    float complex *data;
} mat_fc_t;

extern int mat_fc_create(size_t max_sz, size_t min_sz, mat_fc_t *ma);

extern int mat_fc_delete(mat_fc_t *ma);

extern int mat_fc_twins_create(size_t max_sz, size_t min_sz, mat_fc_t *ma, mat_fc_t *mb);

extern int mat_fc_twins_reset(mat_fc_t *ma, mat_fc_t *mb);

extern void mat_fc_stdout(mat_fc_t *ma);


typedef struct
{
    size_t row_size;  /* Number of rows */
    size_t col_size;  /* Numbor of columns */
    size_t size;  /* Total size = row_size * col_size */

    double complex *data;
} mat_dc_t;

extern int mat_dc_create(size_t max_sz, size_t min_sz, mat_dc_t *ma);

extern int mat_dc_delete(mat_dc_t *ma);

extern int mat_dc_twins_create(size_t max_sz, size_t min_sz, mat_dc_t *ma, mat_dc_t *mb);

extern int mat_dc_twins_reset(mat_dc_t *ma, mat_dc_t *mb);

extern void mat_dc_stdout(mat_dc_t *ma);


typedef struct
{
    size_t row_size;  /* Number of rows */
    size_t col_size;  /* Numbor of columns */
    size_t size;  /* Total size = row_size * col_size */

    long double complex *data;
} mat_lc_t;

extern int mat_lc_create(size_t max_sz, size_t min_sz, mat_lc_t *ma);

extern int mat_lc_delete(mat_lc_t *ma);

extern int mat_lc_twins_create(size_t max_sz, size_t min_sz, mat_lc_t *ma, mat_lc_t *mb);

extern int mat_lc_twins_reset(mat_lc_t *ma, mat_lc_t *mb);

extern void mat_lc_stdout(mat_lc_t *ma);

extern double clock_difftime(struct timespec *tp_b, struct timespec *tp_e);

#endif
